package cn.turboinfo.fuyang.api.provider.common.service.impl.stat;

import cn.turboinfo.fuyang.api.domain.common.service.category.CategoryService;
import cn.turboinfo.fuyang.api.domain.common.service.company.HousekeepingCompanyService;
import cn.turboinfo.fuyang.api.domain.common.service.dictconfig.DictConfigItemService;
import cn.turboinfo.fuyang.api.domain.common.service.division.DivisionService;
import cn.turboinfo.fuyang.api.domain.common.service.order.ServiceOrderService;
import cn.turboinfo.fuyang.api.domain.common.service.shop.HousekeepingShopService;
import cn.turboinfo.fuyang.api.domain.common.service.staff.HousekeepingStaffService;
import cn.turboinfo.fuyang.api.domain.common.service.stat.IndexStatService;
import cn.turboinfo.fuyang.api.domain.common.service.stat.OrderStatService;
import cn.turboinfo.fuyang.api.domain.common.service.user.UserTypeRelService;
import cn.turboinfo.fuyang.api.domain.util.DateTimeFormatHelper;
import cn.turboinfo.fuyang.api.entity.common.constant.AreaConstants;
import cn.turboinfo.fuyang.api.entity.common.enumeration.company.CompanyStatus;
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderStatus;
import cn.turboinfo.fuyang.api.entity.common.enumeration.staff.StaffStatus;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.UserType;
import cn.turboinfo.fuyang.api.entity.common.pojo.category.Category;
import cn.turboinfo.fuyang.api.entity.common.pojo.company.HousekeepingCompany;
import cn.turboinfo.fuyang.api.entity.common.pojo.company.QHousekeepingCompany;
import cn.turboinfo.fuyang.api.entity.common.pojo.dictconfig.DictConfigItem;
import cn.turboinfo.fuyang.api.entity.common.pojo.division.Division;
import cn.turboinfo.fuyang.api.entity.common.pojo.shop.HousekeepingShop;
import cn.turboinfo.fuyang.api.entity.common.pojo.shop.QHousekeepingShop;
import cn.turboinfo.fuyang.api.entity.common.pojo.staff.HousekeepingStaff;
import cn.turboinfo.fuyang.api.entity.common.pojo.staff.QHousekeepingStaff;
import cn.turboinfo.fuyang.api.entity.common.pojo.stat.IndexAdmin;
import cn.turboinfo.fuyang.api.entity.common.pojo.stat.IndexPortal;
import cn.turboinfo.fuyang.api.entity.common.pojo.stat.OrderStat;
import cn.turboinfo.fuyang.api.provider.common.util.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import net.sunshow.toolkit.core.base.enums.EnableStatus;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.helper.component.request.QPageRequestHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * @author gadzs
 * @description
 * @date 2023/3/7 15:55
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class IndexStatServiceImpl implements IndexStatService {

    public static final String FY_STAT_ADMIN_DATA = "fy:stat:admin:data";
    public static final String FY_STAT_PORTAL_DATA = "fy:stat:portal:data";
    private final RedisUtils redisUtils;
    private final HousekeepingCompanyService housekeepingCompanyService;
    private final UserTypeRelService userTypeRelService;
    private final ServiceOrderService serviceOrderService;
    private final HousekeepingStaffService housekeepingStaffService;
    private final DivisionService divisionService;
    private final DictConfigItemService dictConfigItemService;
    private final HousekeepingShopService housekeepingShopService;
    private final OrderStatService orderStatService;
    private final CategoryService categoryService;


    @Override
    public void setStatAdminData() {
        IndexAdmin indexAdmin = getStatAdminData();
        if (Objects.isNull(indexAdmin)) {
            indexAdmin = new IndexAdmin();
        }
        // 企业数据
        val request = QRequest.newInstance()
                .filterEqual(QHousekeepingCompany.status, CompanyStatus.REVIEWED);
        val requestPage = QPage.newInstance()
                .paging(0, 100);
        AtomicLong totalCompanyNum = new AtomicLong(0L);
        AtomicLong totalShopNum = new AtomicLong(0L);
        AtomicLong totalStaffNum = new AtomicLong(0L);
        AtomicLong totalOrderNum = new AtomicLong(0L);
        List<HousekeepingCompany> companyList = QPageRequestHelper.request(request, requestPage, housekeepingCompanyService::findAll);
        companyList
                .forEach(it -> {
                    totalCompanyNum.getAndIncrement();
                    totalShopNum.addAndGet(it.getShopNum());
                    totalStaffNum.addAndGet(it.getStaffNum());
                    totalOrderNum.addAndGet(it.getOrderNum());
                });
        indexAdmin.setTotalCompanyNum(totalCompanyNum.get());
        indexAdmin.setTotalShopNum(totalShopNum.get());
        indexAdmin.setTotalStaffNum(totalStaffNum.get());
        indexAdmin.setTotalOrderNum(totalOrderNum.get());
        // 消费者
        indexAdmin.setTotalCustomerNum(userTypeRelService.countByUserType(UserType.Consumer));
        // 交易额
        indexAdmin.setTotalOrderAmount(serviceOrderService.sumAmountByStatus(ServiceOrderStatus.COMPLETED));

        // 公司订单
        val orderCompanyTrend = companyList.stream()
                .map(it -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", StringUtils.isNotBlank(it.getShortName()) ? it.getShortName() : it.getName());
                    map.put("value", it.getOrderNum());
                    return map;
                })
                .toList();

        indexAdmin.setOrderCompanyTrend(orderCompanyTrend);

        // 订单当月的
        val localDateTime = LocalDateTime.now();
        String currentMongth = DateTimeFormatHelper.format(localDateTime, "yyyy-MM");
        val orderMonthTrend = indexAdmin.getOrderMonthTrend();
        if (orderMonthTrend.size() > 12) {
            indexAdmin.setOrderMonthTrend(orderMonthTrend.subList(orderMonthTrend.size() - 12, orderMonthTrend.size()));
        }
        Map<String, Object> mapOrderTrend = new HashMap<>();
        mapOrderTrend.put("time", currentMongth);
        mapOrderTrend.put("data", serviceOrderService.countOrder(ServiceOrderStatus.COMPLETED, DateTimeFormatHelper.firstDayOfMonth(
                localDateTime), localDateTime).intValue());
        if (orderMonthTrend.size() > 0) {
            val stringObjectMap = orderMonthTrend.get(orderMonthTrend.size() - 1);
            if (stringObjectMap.get("time").toString().equals(currentMongth)) {
                orderMonthTrend.remove(indexAdmin.getOrderMonthTrend().size() - 1);
            }
        }
        orderMonthTrend.add(mapOrderTrend);

        // 注册趋势
        val customerMonthTrend = indexAdmin.getCustomerMonthTrend();
        if (customerMonthTrend.size() > 12) {
            indexAdmin.setCustomerMonthTrend(customerMonthTrend.subList(customerMonthTrend.size() - 12, customerMonthTrend.size()));
        }
        Map<String, Object> mapCustomerTrend = new HashMap<>();
        mapCustomerTrend.put("time", currentMongth);
        mapCustomerTrend.put("data", userTypeRelService.countUser(UserType.Consumer, DateTimeFormatHelper.firstDayOfMonth(
                localDateTime), localDateTime).intValue());
        if (customerMonthTrend.size() > 0) {
            val stringObjectMap = customerMonthTrend.get(customerMonthTrend.size() - 1);
            if (stringObjectMap.get("time").toString().equals(currentMongth)) {
                customerMonthTrend.remove(customerMonthTrend.size() - 1);
            }
        }
        customerMonthTrend.add(mapCustomerTrend);

        // 订单类型统计
        List<Category> categoryList = categoryService.findAllChildren();
        Set<Long> categoryIdSet = categoryList.stream()
                .map(Category::getId)
                .collect(Collectors.toSet());

        Map<Long, Long> categoryOrderCountMap = orderStatService.findByCategoryIdCollection(categoryIdSet)
                .stream()
                .collect(Collectors.groupingBy(OrderStat::getId, Collectors.summingLong(OrderStat::getOrderCount)));

        val orderCategoryTrend = categoryList.stream()
                .map(it -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", it.getName());
                    if (categoryOrderCountMap.containsKey(it.getId())) {
                        map.put("value", categoryOrderCountMap.get(it.getId()));
                    } else {
                        map.put("value", 0);
                    }
                    return map;
                }).toList();

        indexAdmin.setOrderCategoryTrend(orderCategoryTrend);
        redisUtils.set(FY_STAT_ADMIN_DATA, indexAdmin);
    }

    @Override
    public IndexAdmin getStatAdminData() {
        Object o = redisUtils.get(FY_STAT_ADMIN_DATA);
        if (Objects.nonNull(o)) {
            return (IndexAdmin) o;
        }
        return null;
    }


    @Override
    public void setStatPortalData() {
        IndexPortal indexPortal = getStatPortalData();
        if (Objects.isNull(indexPortal)) {
            indexPortal = new IndexPortal();
        }
        // 企业数据
        val requestCompany = QRequest.newInstance()
                .filterEqual(QHousekeepingCompany.status, CompanyStatus.REVIEWED);
        val requestPage = QPage.newInstance()
                .paging(0, 100);

        val companyMap = QPageRequestHelper.request(requestCompany, requestPage, housekeepingCompanyService::findAll)
                .stream().collect(Collectors.groupingBy(HousekeepingCompany::getHouseKeepingType, Collectors.counting()));
        indexPortal.setCompanyStat(companyMap);

        // 家政员
        List<DictConfigItem> dictConfigItemList = dictConfigItemService.findAllDictConfigItem("staffType");
        if (CollectionUtils.isNotEmpty(dictConfigItemList)) {
            val staffTypeMap = dictConfigItemList.stream().collect(Collectors.toMap(DictConfigItem::getItemName, DictConfigItem::getItemValue));
            val requestStaff = QRequest.newInstance()
                    .filterEqual(QHousekeepingStaff.status, StaffStatus.PUBLISHED);
            val staffList = QPageRequestHelper.request(requestStaff, requestPage, housekeepingStaffService::findAll);
            indexPortal.setStaffNum(staffList.size());
            val staffMap = staffList.stream().collect(Collectors.groupingBy(HousekeepingStaff::getStaffType, Collectors.counting()));
            staffTypeMap.forEach((k, v) -> {
                if (staffMap.containsKey(v)) {
                    staffTypeMap.put(k, staffMap.get(v).toString());
                } else {
                    staffTypeMap.put(k, "0");
                }
            });
            indexPortal.setStaffTypeStat(staffTypeMap);
        }

        // 门店
        val areaMap = divisionService.findByParentId(AreaConstants.DEFAULT_CITY_ID).stream().collect(Collectors.toMap(Division::getAreaName, Division::getId));
        val requestShop = QRequest.newInstance()
                .filterEqual(QHousekeepingShop.status, EnableStatus.ENABLED);
        val shopMap = QPageRequestHelper.request(QRequest.newInstance()
                        .filterEqual(QHousekeepingShop.status, EnableStatus.ENABLED), QPage.newInstance()
                        .paging(0, 1000), housekeepingShopService::findAll)
                .stream().collect(Collectors.groupingBy(HousekeepingShop::getAreaCode, Collectors.counting()));
        areaMap.forEach((k, v) -> areaMap.put(k, shopMap.getOrDefault(v, 0L)));
        indexPortal.setShopAreaStat(areaMap);

        redisUtils.set(FY_STAT_PORTAL_DATA, indexPortal);
    }


    @Override
    public IndexPortal getStatPortalData() {
        Object o = redisUtils.get(FY_STAT_PORTAL_DATA);
        if (Objects.nonNull(o)) {
            return (IndexPortal) o;
        }
        return null;
    }
}
